package com.gome.ocean.service.task;

import java.sql.Connection;
import java.sql.SQLException;
import java.text.MessageFormat;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.quartz.JobExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.druid.pool.DruidDataSource;
import com.gome.ocean.common.enums.DataBaseType;
import com.gome.ocean.common.utils.SpringContextUtil;
import com.gome.ocean.dao.model.gddl.AppConfigBO;
import com.gome.ocean.dao.model.gddl.AppDatasourceBO;
import com.gome.ocean.service.gddl.AppConfigSerivce;
import com.gome.ocean.service.gddl.AppDatasourceService;
import com.taobao.tddl.atom.config.TAtomDsConfDO;

/**
 * 加载数据源
 * 
 * @author haqiaolong 2016年4月14日 下午5:30:26
 * @since 5.0.0
 */
public class LoadDatasourceJobTask extends ScheduledJobTask {

    private static final Logger                 LOG                = LoggerFactory.getLogger(LoadDatasourceJobTask.class);
    private static Map<Long, DataSourceWrapper> appDatasources     = new ConcurrentHashMap<Long, DataSourceWrapper>();
    private AppDatasourceService                appDatasourceService;
    private AppConfigSerivce                    appConfigSerivce;

    private static final MessageFormat          DEFAULT_MYSQL_URL  = new MessageFormat("jdbc:mysql://{0}/{1}");
    private static final MessageFormat          DEFAULT_ORACLE_URL = new MessageFormat("jdbc:oracle:thin:@{0}:{1}");
    public static final int                     DEFAULT_POOL_SIZE  = 1;
    public static final int                     DEFAULT_MAX_POOL_SIZE  = 5;

    @Override
    public boolean checkTask() throws JobExecutionException {
        return true;
    }

    @Override
    public void initTask() throws JobExecutionException {
        if (this.appConfigSerivce == null) this.appConfigSerivce = SpringContextUtil.getBean("appConfigSerivce");
        if (this.appDatasourceService == null) this.appDatasourceService = SpringContextUtil.getBean("appDatasourceService");
    }

    @Override
    public void runTask() throws JobExecutionException {
        List<AppDatasourceBO> datasources = appDatasourceService.findAllDataSource();
        for (AppDatasourceBO appDatasourceBO : datasources) {
            AppConfigBO appConfigBO = appConfigSerivce.findAppConfigBOByAppId(appDatasourceBO.getAppId());
            //开启自动切换 后 在加载数据源 并且检测 否则跳过
            if (appConfigBO != null && appConfigBO.getIsAutoSwitch() == 1) {
                DruidDataSource localDruidDataSource = null;
                if (!appDatasources.containsKey(appDatasourceBO.getId())) {
                    localDruidDataSource = createDruidDataSource(appDatasourceBO);
                    Connection conn = null;
                    try {
                        conn = localDruidDataSource.getConnection();
                    } catch (SQLException e) {
                        LOG.error("init datasource error !" + e);
                        continue;
                    } finally {
                        if (conn != null) {
                            try {
                                conn.close();
                            } catch (SQLException e) {
                            }
                        }
                    }
                    appDatasources.put(appDatasourceBO.getId(), new DataSourceWrapper(localDruidDataSource));
                }
            }
        }
        LOG.info("complete load datasource !");
    }

    /**
     * 创建druid数据源
     * 
     * @param appDatasourceBO
     * @return
     */
    private DruidDataSource createDruidDataSource(AppDatasourceBO appDatasourceBO) {
        DruidDataSource localDruidDataSource = new DruidDataSource();
        localDruidDataSource.setTestOnBorrow(false);
        localDruidDataSource.setTestWhileIdle(true);
        localDruidDataSource.setUsername(appDatasourceBO.getUserName());
        localDruidDataSource.setPassword(appDatasourceBO.getPassword());
        if (appDatasourceBO.getSourceType().equals("oracle")) {
            String jdbcUrl = DEFAULT_ORACLE_URL.format(new Object[] { appDatasourceBO.getJdbcUrl(),
                    appDatasourceBO.getDbName() });
            localDruidDataSource.setDriverClassName(DataBaseType.Oracle.getDriverClassName());
            localDruidDataSource.setUrl(jdbcUrl);
            localDruidDataSource.setDbType(DataBaseType.Oracle.getTypeFullName());
            // localDruidDataSource.setValidationQuery(TAtomConstants.DEFAULT_DRUID_ORACLE_VALIDATION_QUERY);
        } else {
            String jdbcUrl = DEFAULT_MYSQL_URL.format(new Object[] { appDatasourceBO.getJdbcUrl(),
                    appDatasourceBO.getDbName() });
            localDruidDataSource.setDriverClassName(DataBaseType.MySql.getDriverClassName());
            localDruidDataSource.setUrl(jdbcUrl);
            localDruidDataSource.setDbType(DataBaseType.MySql.getTypeFullName());
            // localDruidDataSource.setValidationQuery(TAtomConstants.DEFAULT_DRUID_MYSQL_VALIDATION_QUERY);
        }
        // lazy init 先设置为0 后续真正执行时才创建连接
        localDruidDataSource.setInitialSize(TAtomDsConfDO.defaultInitPoolSize);
        localDruidDataSource.setMinIdle(DEFAULT_POOL_SIZE);
        localDruidDataSource.setMaxActive(DEFAULT_POOL_SIZE);
        // 配置间隔多久才进行一次检测，检测需要关闭的空闲连接，单位是毫秒
        localDruidDataSource.setTimeBetweenEvictionRunsMillis(15 * 60 * 1000);
        // 配置一个连接在池中最小生存的时间，单位是毫秒
        localDruidDataSource.setMinEvictableIdleTimeMillis(15 * 60 * 1000);
        localDruidDataSource.setMaxWait(TAtomDsConfDO.defaultMaxWait);
        appDatasources.put(appDatasourceBO.getId(), new DataSourceWrapper(localDruidDataSource));
        return localDruidDataSource;
    }

    public static void removeDataSource(Long id) {
        appDatasources.remove(id);
    }

    public static Map<Long, DataSourceWrapper> getAppDataSources() {
        return appDatasources;
    }
}
